home *** CD-ROM | disk | FTP | other *** search
/ MacAddict 83 / MacAddict_083_2003-07.iso / mac / Software / Development / VLC Source 0.5.3.dmg / src / video_output / vout_subpictures.c < prev   
C/C++ Source or Header  |  2003-04-07  |  12KB  |  299 lines

  1. /*****************************************************************************
  2.  * vout_subpictures.c : subpicture management functions
  3.  *****************************************************************************
  4.  * Copyright (C) 2000 VideoLAN
  5.  * $Id: vout_subpictures.c,v 1.19 2003/01/30 12:38:13 gbazin Exp $
  6.  *
  7.  * Authors: Vincent Seguin <seguin@via.ecp.fr>
  8.  *          Samuel Hocevar <sam@zoy.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24.  
  25. /*****************************************************************************
  26.  * Preamble
  27.  *****************************************************************************/
  28. #include <stdlib.h>                                                /* free() */
  29. #include <stdio.h>                                              /* sprintf() */
  30. #include <string.h>                                            /* strerror() */
  31.  
  32. #include <vlc/vlc.h>
  33.  
  34. #include "video.h"
  35. #include "video_output.h"
  36.  
  37. /*****************************************************************************
  38.  * vout_DisplaySubPicture: display a subpicture unit
  39.  *****************************************************************************
  40.  * Remove the reservation flag of a subpicture, which will cause it to be
  41.  * ready for display.
  42.  *****************************************************************************/
  43. void  vout_DisplaySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
  44. {
  45.     int         i_margin;
  46.  
  47.     /* Check if status is valid */
  48.     if( p_subpic->i_status != RESERVED_SUBPICTURE )
  49.     {
  50.         msg_Err( p_vout, "subpicture %p has invalid status #%d",
  51.                          p_subpic, p_subpic->i_status );
  52.     }
  53.  
  54.     /* If the user requested an SPU margin, we force the position after
  55.      * having checked that it was a valid value. */
  56.     i_margin = config_GetInt( p_vout, "spumargin" );
  57.  
  58.     if( i_margin >= 0 )
  59.     {
  60.         if( p_subpic->i_height + (unsigned int)i_margin
  61.                                                  <= p_vout->output.i_height )
  62.         {
  63.             p_subpic->i_y = p_vout->output.i_height
  64.                              - i_margin - p_subpic->i_height;
  65.         }
  66.     }
  67.  
  68.     /* Remove reservation flag */
  69.     p_subpic->i_status = READY_SUBPICTURE;
  70. }
  71.  
  72. /*****************************************************************************
  73.  * vout_CreateSubPicture: allocate a subpicture in the video output heap.
  74.  *****************************************************************************
  75.  * This function create a reserved subpicture in the video output heap.
  76.  * A null pointer is returned if the function fails. This method provides an
  77.  * already allocated zone of memory in the spu data fields. It needs locking
  78.  * since several pictures can be created by several producers threads.
  79.  *****************************************************************************/
  80. subpicture_t *vout_CreateSubPicture( vout_thread_t *p_vout, int i_type )
  81. {
  82.     int                 i_subpic;                        /* subpicture index */
  83.     subpicture_t *      p_subpic = NULL;            /* first free subpicture */
  84.  
  85.     /* Get lock */
  86.     vlc_mutex_lock( &p_vout->subpicture_lock );
  87.  
  88.     /*
  89.      * Look for an empty place
  90.      */
  91.     for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
  92.     {
  93.         if( p_vout->p_subpicture[i_subpic].i_status == FREE_SUBPICTURE )
  94.         {
  95.             /* Subpicture is empty and ready for allocation */
  96.             p_subpic = &p_vout->p_subpicture[i_subpic];
  97.             p_vout->p_subpicture[i_subpic].i_status = RESERVED_SUBPICTURE;
  98.             break;
  99.         }
  100.     }
  101.  
  102.     /* If no free subpicture could be found */
  103.     if( p_subpic == NULL )
  104.     {
  105.         msg_Err( p_vout, "subpicture heap is full" );
  106.         vlc_mutex_unlock( &p_vout->subpicture_lock );
  107.         return NULL;
  108.     }
  109.  
  110.     /* Copy subpicture information, set some default values */
  111.     p_subpic->i_type    = i_type;
  112.     p_subpic->i_status  = RESERVED_SUBPICTURE;
  113.  
  114.     p_subpic->i_start   = 0;
  115.     p_subpic->i_stop    = 0;
  116.     p_subpic->b_ephemer = VLC_FALSE;
  117.  
  118.     p_subpic->i_x       = 0;
  119.     p_subpic->i_y       = 0;
  120.     p_subpic->i_width   = 0;
  121.     p_subpic->i_height  = 0;
  122.  
  123.     vlc_mutex_unlock( &p_vout->subpicture_lock );
  124.  
  125.     return p_subpic;
  126. }
  127.  
  128. /*****************************************************************************
  129.  * vout_DestroySubPicture: remove a subpicture from the heap
  130.  *****************************************************************************
  131.  * This function frees a previously reserved subpicture.
  132.  * It is meant to be used when the construction of a picture aborted.
  133.  * This function does not need locking since reserved subpictures are ignored
  134.  * by the output thread.
  135.  *****************************************************************************/
  136. void vout_DestroySubPicture( vout_thread_t *p_vout, subpicture_t *p_subpic )
  137. {
  138.     /* Get lock */
  139.     vlc_mutex_lock( &p_vout->subpicture_lock );
  140.  
  141.     /* There can be race conditions so we need to check the status */
  142.     if( p_subpic->i_status == FREE_SUBPICTURE )
  143.     {
  144.         vlc_mutex_unlock( &p_vout->subpicture_lock );
  145.         return;
  146.     }
  147.  
  148.     /* Check if status is valid */
  149.     if( ( p_subpic->i_status != RESERVED_SUBPICTURE )
  150.            && ( p_subpic->i_status != READY_SUBPICTURE ) )
  151.     {
  152.         msg_Err( p_vout, "subpicture %p has invalid status %d",
  153.                          p_subpic, p_subpic->i_status );
  154.     }
  155.  
  156.     if( p_subpic->pf_destroy )
  157.     {
  158.         p_subpic->pf_destroy( p_subpic );
  159.     }
  160.  
  161.     p_subpic->i_status = FREE_SUBPICTURE;
  162.  
  163.     vlc_mutex_unlock( &p_vout->subpicture_lock );
  164. }
  165.  
  166. /*****************************************************************************
  167.  * vout_RenderSubPictures: render a subpicture list
  168.  *****************************************************************************
  169.  * This function renders all sub picture units in the list.
  170.  *****************************************************************************/
  171. void vout_RenderSubPictures( vout_thread_t *p_vout, picture_t *p_pic,
  172.                              subpicture_t *p_subpic )
  173. {
  174.     /* Get lock */
  175.     vlc_mutex_lock( &p_vout->subpicture_lock );
  176.  
  177.     /* Check i_status again to make sure spudec hasn't destroyed the subpic */
  178.     while( p_subpic != NULL && p_subpic->i_status != FREE_SUBPICTURE )
  179.     {
  180.         p_subpic->pf_render( p_vout, p_pic, p_subpic );
  181.         p_subpic = p_subpic->p_next;
  182.     }
  183.  
  184.     vlc_mutex_unlock( &p_vout->subpicture_lock );
  185. }
  186.  
  187. /*****************************************************************************
  188.  * vout_SortSubPictures: find the subpictures to display
  189.  *****************************************************************************
  190.  * This function parses all subpictures and decides which ones need to be
  191.  * displayed. This operation does not need lock, since only READY_SUBPICTURE
  192.  * are handled. If no picture has been selected, display_date will depend on
  193.  * the subpicture.
  194.  * We also check for ephemer DVD subpictures (subpictures that have
  195.  * to be removed if a newer one is available), which makes it a lot
  196.  * more difficult to guess if a subpicture has to be rendered or not.
  197.  *****************************************************************************/
  198. subpicture_t *vout_SortSubPictures( vout_thread_t *p_vout,
  199.                                     mtime_t display_date )
  200. {
  201.     int i_index;
  202.     subpicture_t *p_subpic     = NULL;
  203.     subpicture_t *p_ephemer    = NULL;
  204.     mtime_t       ephemer_date = 0;
  205.  
  206.     /* We get an easily parsable chained list of subpictures which
  207.      * ends with NULL since p_subpic was initialized to NULL. */
  208.     for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ )
  209.     {
  210.         if( p_vout->p_subpicture[i_index].i_status == READY_SUBPICTURE )
  211.         {
  212.             /* If it is a DVD subpicture, check its date */
  213.             if( p_vout->p_subpicture[i_index].i_type == MEMORY_SUBPICTURE )
  214.             {
  215.                 if( !p_vout->p_subpicture[i_index].b_ephemer
  216.                      && display_date > p_vout->p_subpicture[i_index].i_stop )
  217.                 {
  218.                     /* Too late, destroy the subpic */
  219.                     vout_DestroySubPicture( p_vout,
  220.                                     &p_vout->p_subpicture[i_index] );
  221.                     continue;
  222.                 }
  223.  
  224.                 if( display_date
  225.                      && display_date < p_vout->p_subpicture[i_index].i_start )
  226.                 {
  227.                     /* Too early, come back next monday */
  228.                     continue;
  229.                 }
  230.  
  231.                 /* If this is an ephemer subpic, see if it's the
  232.                  * youngest we have */
  233.                 if( p_vout->p_subpicture[i_index].b_ephemer )
  234.                 {
  235.                     if( p_ephemer == NULL )
  236.                     {
  237.                         p_ephemer = &p_vout->p_subpicture[i_index];
  238.                         continue;
  239.                     }
  240.  
  241.                     if( p_vout->p_subpicture[i_index].i_start
  242.                                                      < p_ephemer->i_start )
  243.                     {
  244.                         /* Link the previous ephemer subpicture and
  245.                          * replace it with the current one */
  246.                         p_ephemer->p_next = p_subpic;
  247.                         p_subpic = p_ephemer;
  248.                         p_ephemer = &p_vout->p_subpicture[i_index];
  249.  
  250.                         /* If it's the 2nd youngest subpicture,
  251.                          * register its date */
  252.                         if( !ephemer_date
  253.                               || ephemer_date > p_subpic->i_start )
  254.                         {
  255.                             ephemer_date = p_subpic->i_start;
  256.                         }
  257.  
  258.                         continue;
  259.                     }
  260.                 }
  261.  
  262.                 p_vout->p_subpicture[i_index].p_next = p_subpic;
  263.                 p_subpic = &p_vout->p_subpicture[i_index];
  264.  
  265.                 /* If it's the 2nd youngest subpicture, register its date */                    if( !ephemer_date || ephemer_date > p_subpic->i_start )
  266.                 {
  267.                     ephemer_date = p_subpic->i_start;
  268.                 }
  269.             }
  270.             /* If it's not a DVD subpicture, just register it */
  271.             else
  272.             {
  273.                 p_vout->p_subpicture[i_index].p_next = p_subpic;
  274.                 p_subpic = &p_vout->p_subpicture[i_index];
  275.             }
  276.         }
  277.     }
  278.  
  279.     /* If we found an ephemer subpicture, check if it has to be
  280.      * displayed */
  281.     if( p_ephemer != NULL )
  282.     {
  283.         if( p_ephemer->i_start < ephemer_date )
  284.         {
  285.             /* Ephemer subpicture has lived too long */
  286.             vout_DestroySubPicture( p_vout, p_ephemer );
  287.         }
  288.         else
  289.         {
  290.             /* Ephemer subpicture can still live a bit */
  291.             p_ephemer->p_next = p_subpic;
  292.             return p_ephemer;
  293.         }
  294.     }
  295.  
  296.     return p_subpic;
  297. }
  298.  
  299.